package com.imooc.business.core.executor.query.base;

import com.imooc.business.context.DataContext;
import com.imooc.business.core.executor.query.db.QueryDbService;
import com.imooc.infra.repository.jdbc.params.StandardSqlParam;
import com.imooc.module.collect.enums.DimensionEnum;
import com.imooc.module.collect.request.ParamsRequest;
import com.imooc.module.query.request.QueryRequest;
import com.imooc.module.query.response.QueryDataResponse;
import com.imooc.module.reponse.DataResponse;
import com.imooc.user.provider.service.UserCenterGroupService;
import com.imooc.user.provider.service.UserCenterUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 报表基类
 * @param <T>
 * @param <k>
 */
@Slf4j
public abstract class AbstractTableService<T,k> implements ResultService<T,k> {

    @DubboReference(check = false)
    protected UserCenterUserService userService;

    @DubboReference(check = false)
    protected UserCenterGroupService groupService;

    @Autowired
    private QueryDbService queryDbService;

    /**
     * 组装数据
     * @param context
     * @param <K>
     */
    @Override
    public <K>void buildResult(DataContext context) {
        ParamsRequest paramsRequest = context.getRequest();
        QueryRequest request = paramsRequest.getQueryRequest();
        DataResponse dataResponse = context.getResponse();

        DataResponse.Table table = dataResponse.getTable();
        List<QueryDataResponse.TableData> dataList = table.getDataList();
        //查询到当前维度 组织结构
        List<T> organList = getOrganList(request);
        //获取到当前组织结构 指标数据
        Map<Object, Map<String, Object>> dataMap = getDataMap(request, organList);
        setResponseHeader(request, dataResponse);
        //合并 组织和指标数据
        combineResult(organList, dataMap, dataList, request);
    }

    /**
     * 设置表格头名称
     * @param request
     * @param dataResponse
     */
    private void setResponseHeader(QueryRequest request, DataResponse dataResponse) {
        DataResponse.Table table = dataResponse.getTable();
        table.setColumns(request.getZhNames().toArray(new String[]{}));
        table.setBusinessName(request.getBusinessName());
    }


    /**
     * 合并数据
     * @param organList
     * @param dataMap
     * @param dataList
     * @param request
     * @param <K>
     */
    public <K>void combineResult(List<T> organList, Map<Object, Map<String, Object>> dataMap, List<QueryDataResponse.TableData> dataList, QueryRequest request){
        if ( Objects.isNull(dataMap) || dataMap.size() == 0 || CollectionUtils.isEmpty(organList)){
            return;
        }
        Set<String> indexNames = request.getIndexNames();
        int indexSize = indexNames.size();
        Double[] summaryArr = new Double[indexSize+1];
        if (dataList.size()>0){
            QueryDataResponse.TableData initData = dataList.remove(0);
            String[] columns = initData.getColumns();
            for (int i=1; i< indexSize+1 ; i++){
                summaryArr[i] = Double.valueOf(columns[i]);
            }
        } else {
            for (int i=0; i<indexSize+1; i++){
                summaryArr[i] = 0d;
            }
        }

        for (T organ : organList) {
            QueryDataResponse.TableData tableData = new QueryDataResponse.TableData();
            setSumaryAndClickAble(tableData, organ);

            String[] columns = new String[indexSize+1];
            columns[0] = getName(organ);
            for (int i=1; i< indexSize+1; i++){
                columns[i] = "0";
            }

            K organId = getOrganId(organ);
            if (dataMap.containsKey(organId)) {
                Map<String, Object> indexMap = dataMap.get(organId);
                int i=1;
                for (String sign: indexNames){
                    String signStr = indexMap.get(sign).toString();
                    summaryArr[i] += Double.parseDouble(signStr.trim());
                    columns[i++] = String.valueOf(Double.valueOf(signStr.trim()));
                }
            }
            tableData.setColumns(columns);
            dataList.add(tableData);
        }

        QueryDataResponse.TableData summaryData = new QueryDataResponse.TableData();
        summaryData.setIsSummary(true);
        summaryData.setClickAble(false);
        String[] columns = new String[indexSize+1];
        columns[0] = "合计";
        for (int i=1; i<summaryArr.length; i++){
            columns[i] = summaryArr[i] == null ? "0":String.valueOf(summaryArr[i]);
        }
        summaryData.setColumns(columns);
        dataList.add(0, summaryData);
    }


    /**
     * 执行数据查询
     * @param request
     * @return
     */
    protected Map<Object, Map<String,Object>> execQuery(QueryRequest request){
        List<Long> userIds = request.getUserIds();
        List<String> groupIds = request.getGroupIds();
        List<Long> schoolIds = request.getSchoolIds();

        boolean execFlag = false;
        String userName = "";
        if (CollectionUtils.isNotEmpty(userIds)) {
            request.setDimension(DimensionEnum.USER);
            userName = StandardSqlParam.USER_ID;
            execFlag = true;
        }
        if (CollectionUtils.isNotEmpty(groupIds)) {
            request.setDimension(DimensionEnum.GROUP);
            userName = StandardSqlParam.GROUP_ID;
            execFlag = true;
        }
        if (CollectionUtils.isNotEmpty(schoolIds)) {
            request.setDimension(DimensionEnum.SCHOLL);
            userName = StandardSqlParam.SCHOOL_ID;
            execFlag = true;
        }
        if (!execFlag){
            return new HashMap<>();
        }
        List<Map<String, Object>> mapList = queryDbService.execQuery(request);

        if (CollectionUtils.isEmpty(mapList)){
            return new HashMap<>();
        }

        String finalUserName = userName;
        return mapList.stream().collect(Collectors.toMap(m->m.get(finalUserName), Function.identity(), (v1, v2)->{
            for (Map.Entry<String, Object> entry : v1.entrySet()) {
                String key = entry.getKey();
                if (finalUserName.equals(key)){
                    continue;
                }
                Object value1 = Objects.isNull(entry.getValue()) ? 0 : entry.getValue();
                Object value2 = Objects.isNull(v2.get(key)) ? 0 : v2.get(key);
                v2.put(key, Double.valueOf(value1.toString()) + Double.valueOf(value2.toString()));
            }
            return v2;
        }));
    }


    /**
     * 获取组织
     * @param request
     * @return
     */
    protected abstract List<T> getOrganList(QueryRequest request);

    /**
     * 获取指标数据
     * @param request
     * @param organs
     * @return
     */
    protected abstract Map<Object, Map<String, Object>> getDataMap(QueryRequest request, List<T> organs);


    protected abstract void setSumaryAndClickAble(QueryDataResponse.TableData tableData, T organ);

    protected abstract String getName(T organ);

    protected abstract <K>K getOrganId(T organ);

}
